<!DOCTYPE html>
<html lang="en">
<!---
https://cdn.bootcdn.net/ajax/libs/three.js/0.166.1/three.module.js
比如安装148版本
npm install three@0.148.0 save
-->
<head>
    <meta charset="UTF-8">
    <title>cube</title>
    <script type="importmap">
        {
          "imports": {
            "three": "./js/threejs/three.module.js",
            "three/addons/": "./js/jsm/"
          }
        }
    </script>
<style>
  body {
	  margin: 0;
	  background-color: #000;
	  color: #fff;
	  font-family: Monospace;
	  font-size: 13px;
	  line-height: 24px;
	  overscroll-behavior: none;
  }

  canvas {
      display: block;
  }

  #tooltip {
      position: absolute;
      background-color: rgba(0, 0, 0, 0.7);
      color: white;
      padding: 5px;
      border-radius: 5px;
      display: none;
      /* 默认隐藏 */
      pointer-events: none;
      font-size: 12px;
      white-space: break-spaces;
      z-index: 1;
  }
</style>
</head>
<body>
<!-- 创建用于显示提示的文本元素 -->
<div id="container"></div>
<div id="tooltip" onclick="tooltipCkick"></div>
<script type="module">
	import * as THREE from "./js/threejs/three.module.js";
	import { OrbitControls } from './js/threejs/jsm/controls/OrbitControls.js';

	var scene,camera,renderer,container;
	var raycaster = new THREE.Raycaster();
    var pointer = new THREE.Vector2();

	initScene();
	render();


	var gOptArry = [
		{postion:[{x:0  ,y:0  },{x:200,y:100}],pic:'./img/p01.png',title:'p01'},
		{postion:[{x:200,y:0  },{x:200,y:100}],pic:'./img/p02.png',title:'p02'},
		{postion:[{x:0,y:100  },{x:200,y:100}],pic:'./img/p03.png',title:'p03'},
		{postion:[{x:200  ,y:100},{x:200,y:100}],pic:'./img/p04.png',title:'p04'},
        {postion:[{x:400,y:0},{x:100,y:100}],color:'#8833ff',title:'#8833ff'},
        {postion:[{x:400,y:100},{x:100,y:100}],color:'#ff3333',title:'#ff3333'}
	]
	let optparams = {
    	size : { x:540, y:240, z:240 },
        faceIdx : 2  //填充面序号
	};
    createCube(optparams, gOptArry);

    function createCube (optparams, optArry) {
		let ldrawnum = 0;
        if ( optparams === undefined || optparams === null ) optparams = {};
        let params = JSON.parse( JSON.stringify(optparams) );
        let ratio = 1;
        let vWidth = params.hasOwnProperty("size") ? params["size"].x : 128;
        let vheight = params.hasOwnProperty("size") ? params["size"].z : 64;

        if(params.ratio) ratio = params.ratio;
        let lcanvas = document.createElement('canvas');
        lcanvas.width = vWidth*ratio;
        lcanvas.height = vheight*ratio;
        lcanvas.style.width = vWidth+'px';
        lcanvas.style.height = vheight+'px';
        let lcontext = lcanvas.getContext('2d');

        lcontext.clearRect(0,0,vWidth,vheight);
        lcontext.fillStyle = "rgba(255,255,255,1)";
        lcontext.fillRect(0,0,vWidth,vheight);

        function finish() {
            ldrawnum++;
            if(ldrawnum>=optArry.length) {
                lcontext.scale(ratio,ratio);

                let texture = new THREE.Texture(lcanvas);
                texture.needsUpdate = true;//, color: 0xff00ff, fog: true
                var material = new THREE.MeshPhongMaterial( { map: texture} );
                var material2 = new THREE.MeshPhongMaterial( { color: 0xffffff} );
                let geometry = new THREE.BoxGeometry(vWidth,vheight, params.size.y);
                const mesh = new THREE.Mesh(geometry, [material,material2]);
                mesh.material.map.needsUpdate = true;

                mesh.geometry.groups = [
                    {
                        "start": 0,
                        "count": 6,
                        "materialIndex": 1
                    },
                    {
                        "start": 6,
                        "count": 6,
                        "materialIndex": 1
                    },
                    {
                        "start": 12,
                        "count": 6,
                        "materialIndex": 1
                    },
                    {
                        "start": 18,
                        "count": 6,
                        "materialIndex": 1
                    },
                    {
                        "start": 24,
                        "count": 6,
                        "materialIndex": 1
                    },
                    {
                        "start": 30,
                        "count": 6,
                        "materialIndex": 1
                    }
                ];
                mesh.geometry.groups[params.faceIdx].materialIndex = 0;
                scene.add(mesh);
			}
        }

        let optItem;
        for(let i=0;i<optArry.length;i++) {
            optItem = optArry[i];
            fillImg(lcontext,lcanvas,optItem,undefined,ratio,finish);
		}
    }

    function fillImg (lcontext,lcanvas,params,type,ratio,callback) {
        var _this = this;
        let imgurl = params.hasOwnProperty("pic") ? params["pic"] : "";
        let x = params.postion[0].x,y = params.postion[0].y;
        let width = params.postion[1].x,height = params.postion[1].y;

        if ( imgurl != undefined && imgurl != null && imgurl != '' ) {

            try {
                let vImg = new Image();
                vImg.src = imgurl;
                const loader = new THREE.ImageLoader();
                loader.load(imgurl,
                    function ( image ) {
                        lcontext.drawImage(image, x, y, width,height);
                        callback();
                    },
                    undefined,
                    function () {
                        console.error( 'An error happened.' );
                        callback();
                    }
                );

            } catch(err){
                console.log(err);
            }
        } else {
            var vbkColor = params.hasOwnProperty("color") ? params["color"] : { r:255, g:255, b:255, a:1.0 };
            // let crgba = hexToRgb(vbkColor).rgb;
            lcontext.fillStyle = vbkColor;
            lcontext.fillRect(x, y, width,height);
            callback();
        }

    }

    function getDatetime() {
        const now = new Date();

        const year = now.getFullYear();
        const month = ('0' + (now.getMonth() + 1)).slice(-2);
        const day = ('0' + now.getDate()).slice(-2);
        const hours = ('0' + now.getHours()).slice(-2);
        const minutes = ('0' + now.getMinutes()).slice(-2);
        const seconds = ('0' + now.getSeconds()).slice(-2);

        const formattedTime = year + month + day + ' ' + hours +':' +  minutes+':' + seconds;

		return formattedTime;
    }

	//初始化场景
	function initScene(){
		// 创建场景
		scene = new THREE.Scene();
		scene.background = new THREE.Color(0x000000)

        container = document.getElementById( 'container' );
		// 创建相机
		camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.1, 10000);
		camera.position.x = -300;
		camera.position.y = 100;
		camera.position.z += 400;

		// 创建渲染器
		renderer = new THREE.WebGLRenderer({ antialias: true });
		// 渲染器能够渲染阴影效果
		renderer.shadowMap.enabled = true;
        renderer.setSize( window.innerWidth, window.innerHeight );
        container.appendChild(renderer.domElement);


		// 添加网格辅助器
		const gridHelper = new THREE.GridHelper(5000, 50); // 创建一个200单位的网格，细分为50个方格
		// gridHelper.rotation.x = 0.5 * Math.PI
        gridHelper.position.y = -150;
		scene.add(gridHelper);

		// 方向光
		const directionalLight = new THREE.DirectionalLight(0xFFFFFF, 1);
		directionalLight.position.set(10, 10, 10);

		directionalLight.shadow.mapSize.width = 1024  // default
		directionalLight.shadow.mapSize.height = 1024  // default
		directionalLight.shadow.camera.near = 0.05  // default
		directionalLight.shadow.camera.far = 500  // default
		//将范围调大
		directionalLight.shadow.camera.top = 20 /// 这个是生效的属性
		directionalLight.shadow.camera.right = 20
		directionalLight.shadow.camera.left = -20
		directionalLight.shadow.camera.bottom = -20
		directionalLight.castShadow = true;
		scene.add(directionalLight);

		// 环境光
		const ambientLight = new THREE.AmbientLight(0xffffff, 2);
		scene.add(ambientLight);

		// 添加鼠标控制
		const controls = new OrbitControls(camera, renderer.domElement);
		// controls.enableDamping = true; // 使得相机移动更加平滑
		controls.dampingFactor = 0.05; // 阻尼效果

        window.addEventListener( 'pointerup', onPointerUp );
        window.addEventListener( 'resize', onWindowResize, false );
	}

    function onPointerUp( event ) {

        // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)

        pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

        raycaster.setFromCamera( pointer, camera );

        // 计算物体和射线的焦点
        const intersects = raycaster.intersectObjects( scene.children );
		if(intersects.length>0) {
			let intersectObj = intersects[ 0 ];
            if( intersectObj.uv ) {
                let optItem,bcheck=false;
                if(0==intersectObj.face.materialIndex) {
                    let uvx = intersectObj.uv.x * optparams.size.x;
                    let uvy = (1-intersectObj.uv.y) * optparams.size.y;
					
                    for(let i=0;i<gOptArry.length;i++) {
                        optItem = gOptArry[i];
                        if( optItem.postion[0].x<=uvx && optItem.postion[0].y<=uvy &&
                            (optItem.postion[0].x+optItem.postion[1].x)>=uvx && (optItem.postion[0].y+optItem.postion[1].y)>=uvy) {
                            bcheck=true;
                            console.log('拾取第'+(i+1)+'图片');
                            alert(optItem.title);
                            break;
                        }
                    }
				}

                if(!bcheck) {
                    alert(getDatetime());
				}
			}
        }

    }

    function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize( window.innerWidth, window.innerHeight );

    }

	function render() {
		// 渲染
		requestAnimationFrame(render);
		renderer.render(scene, camera);
	}

</script>

</body>
</html>
